<?php

namespace app\process;

use Exception;
use support\Log;
use support\think\Db;
use Workerman\Mqtt\Client;
use Workerman\Worker;

// windows 上的MQTT消息处理
// https://www.workerman.net/doc/workerman/components/workerman-mqtt.html 文档地址，AI是个坑
class MqttWindowsListener
{
    // MQTT 服务器配置
    private $mqttConfig = [
        'host' => 'dev.fepft.com', // MQTT 服务器地址
        'port' => 1883, // 端口（加密连接用8883）
        'client_id' => 'webman_mqtt_', // 客户端ID（需唯一）
        'username' => 'dingweiqi', // 认证用户名（可选）
        'password' => 'maxhom168', // 认证密码（可选）
        'keepalive' => 100, // 心跳间隔（秒）
    ];

    // 要监听的主题（支持通配符）
    private $topics = [
        '/server/#' => 0, // 主题 => QoS等级
    ];

    // 重连次数
    private $reconnect_time = 0;
    // 最大重连次数
    private $max_reconnect_time = 5;

    private $coroutinePool;     // 协程池
    private $poolSize = 5;      // 协程数量（根据业务调整）
    private $mqttClient;        // mqtt客户端
    private MqttDataHandle $handler; // 数据处理器

    // 构造函数中补充动态计算的配置
    public function __construct()
    {
        $this->handler = new MqttDataHandle();
        // 在这里使用 uniqid() 生成动态 client_id
        $this->mqttConfig['client_id'] = $this->mqttConfig['client_id'] . uniqid();
    }

    public function onWorkerStart(Worker $worker)
    {
        // 连接 MQTT 服务器
        $client = new Client("mqtt://dev.fepft.com:1883", [
            'client_id' => $this->mqttConfig['client_id'],
            'username' => $this->mqttConfig['username'],
            'password' => $this->mqttConfig['password'],
            'keepalive' => $this->mqttConfig['keepalive'],
            'protocol_level'=>5, // 用最新的5版本，不然只能解析到json数据了
        ]);
        $this->mqttClient = $client;

        // 连接成功回调
        $client->onConnect = function ($client) {            
            // 订阅指定主题
            $client->subscribe($this->topics);
        };

        // 接收消息回调（核心：处理消息逻辑）
        $client->onMessage = function ($topic, $content) {
            $this->handler->handleData($topic, $content, $this->mqttClient);
        };

        // 连接断开回调（自动重连）
        $client->onClose = function ($client) {
            printMqttLog("MQTT 连接断开，5秒后尝试重连...\n");
            \Workerman\Timer::add(5, function () use ($client) {
                $client->connect();
            }, null, false);

            $this->reconnect_time++;
            if ($this->reconnect_time > $this->max_reconnect_time) {
                printMqttLog("重连次数超过 {$this->max_reconnect_time} 次，程序退出...\n");
                exit;
            }
        };

        // 连接错误回调
        $client->onError = function (Exception $ex) {
            $code = $ex->getCode();
            $message = $ex->getMessage();
            printMqttLog("MQTT 错误 - 代码: { $code }, 消息: { $message } \n");
        };

        // 启动连接
        $client->connect();
    }

}
